package org.spring.springboot.util.http;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.DeflateDecompressingEntity;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;


@Component
public class HttpAPIService {

    @Autowired
    private CloseableHttpClient httpClient;

    @Autowired
    private RequestConfig config;


    /**
     * 不带参数的get请求，如果状态码为200，则返回body，如果不为200，则返回null
     * 
     * @param url
     * @return
     * @throws Exception
     */
    public String doGet(String url) throws Exception {
        // 声明 http get 请求
        HttpGet httpGet = new HttpGet(url);

        // 装载配置信息
        httpGet.setConfig(config);

        // 发起请求
        CloseableHttpResponse response = this.httpClient.execute(httpGet);

        // 判断状态码是否为200
        if (response.getStatusLine().getStatusCode() == 200) {
            // 返回响应体的内容
            return EntityUtils.toString(response.getEntity(), "UTF-8");
        }
        return null;
    }

    /**
     * 带参数的get请求，如果状态码为200，则返回body，如果不为200，则返回null
     * 
     * @param url
     * @return
     * @throws Exception
     */
    public String doGet(String url, Map<String, Object> map) throws Exception {
        URIBuilder uriBuilder = new URIBuilder(url);

        if (map != null) {
            // 遍历map,拼接请求参数
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
            }
        }

        // 调用不带参数的get请求
        return this.doGet(uriBuilder.build().toString());

    }

    public HttpResult doPosts(String url, Map<String, String> map) throws Exception {
        Map<String, Object> nmap=new HashMap<String, Object>();
        return doPost(url,nmap);
    }
    /**
     * 带参数的post请求
     * 
     * @param url
     * @param map
     * @return
     * @throws Exception
     */
    public HttpResult doPost(String url, Map<String, Object> map) throws Exception {
        // 声明httpPost请求
        HttpPost httpPost = new HttpPost(url);
        // 加入配置信息
        httpPost.setConfig(config);

        // 判断map是否为空，不为空则进行遍历，封装from表单对象
        if (map != null) {
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                list.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
            }
            // 构造from表单对象
            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, "UTF-8");

            // 把表单放到post里
            httpPost.setEntity(urlEncodedFormEntity);
        }

        // 发起请求
        CloseableHttpResponse response = this.httpClient.execute(httpPost);
        return new HttpResult(response.getStatusLine().getStatusCode(), EntityUtils.toString(
                response.getEntity(), "UTF-8"));
    }

    /**
     * 不带参数post请求
     * 
     * @param url
     * @return
     * @throws Exception
     */
    public HttpResult doPost(String url) throws Exception {
        return this.doPost(url, null);
    }

    /**
     * 中转文件
     * @param file
     * @param remote_url
     * @param fileAppId
     * @param path
     * @param fileName
     * @return
     */
    public String postFile(MultipartFile file,String remote_url, String fileAppId, String path , String fileName) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";
        try {
            fileName = (fileName!=null?fileName:file.getOriginalFilename());
            HttpPost httpPost = new HttpPost(remote_url);
            // 加入配置信息
            httpPost.setConfig(config);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            ContentType fileContent=ContentType.create("multipart/form-data",Charset.forName("GB2312"));
            builder.addBinaryBody("file", file.getInputStream(), fileContent, fileName);// 文件流
            ContentType strContent=ContentType.create("text/plain",Charset.forName("UTF-8"));
            builder.addTextBody("fileName", fileName,strContent);// 类似浏览器表单提交，对应input的name和value
            builder.addTextBody("name", fileName,strContent);// 类似浏览器表单提交，对应input的name和value
            builder.addTextBody("appId", fileAppId,strContent);
            builder.addTextBody("path", path,strContent);
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            HttpResponse response = httpClient.execute(httpPost);// 执行提交
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                // 将响应内容转换为字符串
                result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 下载文件
     *
     * @param remote_url          http://www.xxx.com/img/333.jpg
     * @param destFileName        xxx.jpg/xxx.png/xxx.txt
     */
    public void getFile(String remote_url,String destFileName) throws IOException {
        // 生成一个httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpget = new HttpGet(remote_url);
        HttpResponse response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
        InputStream in = entity.getContent();
        File file = new File(destFileName);
        try {
            FileOutputStream fout = new FileOutputStream(file);
            int l = -1;
            byte[] tmp = new byte[1024];
            while ((l = in.read(tmp)) != -1) {
                fout.write(tmp, 0, l);
                // 注意这里如果用OutputStream.write(buff)的话，图片会失真，大家可以试试
            }
            fout.flush();
            fout.close();
        } finally {
            // 关闭低层流。
            in.close();
        }
       // httpclient.close();
    }

    /**** ***/
    private String httpElementCharset = "utf8";
    private String contentCharset = "utf8";
    private static final int CONNECT_TIMEOUT = 10000;
    private static final int SOCKET_TIMEOUT = 10000;

    public String post(String url, String request, Map<String, String> headers) throws Exception {
        return doPost(url, request, headers);
    }
    public String post(String url, String request) throws Exception {
        return doPost(url, request, null);
    }
    public String get(String url) throws Exception {
        String htmlContent = null;
        String htmlEncoding = httpElementCharset;

        String curUrl = URLEncodeOfCharset(url, htmlEncoding);

        HttpGet post = new HttpGet(curUrl.trim());
        // if (attrib.getSession().getReferer() != null) {
        // post.addHeader("Referer", attrib.getSession().getReferer().trim());
        // }
        // if (attrib.getSession().getCookie() != null) {
        // httpClient.setCookieStore(attrib.getSession().getCookie());
        // }

        try {
            //设置超时
            RequestConfig config = RequestConfig.custom().setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).build();
            post.setConfig(config);
            HttpResponse rsp = httpClient.execute(post);

            curUrl = url;
            // attrib.getSession().setReferer(attrib.getUrl());

            // if (attrib.getSession().getCookie() == null) {
            // attrib.getSession().setCookie(httpClient.getCookieStore());
            // }
            HttpEntity entity = rsp.getEntity();
            htmlContent = new String(GetContentBytes(entity), GetContentType(
                    entity, htmlEncoding));

            if (entity != null) {
                try {
                    EntityUtils.consume(entity);
                } catch (IOException localIOException1) {
                }
            }
        } catch (UnsupportedEncodingException uee) {
            throw uee;
        } catch (ClientProtocolException cpe) {
            throw cpe;
        } catch (IOException ioe) {
            throw ioe;
        }finally{
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return htmlContent;
    }
    private String doPost(String url, String request, Map<String, String> headers) throws Exception {
        String htmlContent = null;
        String htmlEncoding = httpElementCharset;

        HttpPost post = new HttpPost(url);
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                post.addHeader(entry.getKey(), entry.getValue());
            }
        }
        try {
            if(request!=""&&request!=null) {
                post.setEntity(new StringEntity(request, contentCharset));
            }
            //设置超时
            RequestConfig config = RequestConfig.custom().setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).build();
            post.setConfig(config);
            HttpResponse rsp = httpClient.execute(post);
            HttpEntity entity = rsp.getEntity();
            htmlContent = new String(GetContentBytes(entity), GetContentType(
                    entity, htmlEncoding));

            if (entity != null) {
                try {
                    EntityUtils.consume(entity);
                } catch (IOException localIOException1) {
                }
            }
        } catch (UnsupportedEncodingException uee) {
            throw uee;
        } catch (ClientProtocolException cpe) {
            throw cpe;
        } catch (IOException ioe) {
            throw ioe;
        }
        return htmlContent;
    }


    private static String URLEncodeOfCharset(String urlSrc, String encoding) throws URISyntaxException, UnsupportedEncodingException {
        StringBuffer buffer = new StringBuffer();
        try {
            URI uri = new URI(urlSrc);
            if (uri.getQuery() == null) {
                return uri.toString();
            }
            buffer.append(uri.getScheme()).append("://").append(uri.getHost());
            if (uri.getPort() > 0) {
                buffer.append(":").append(uri.getPort());
            }
            buffer.append(uri.getPath());

            List<NameValuePair> queryList = URLEncodedUtils
                    .parse(uri, encoding);
            for (int i = 0; i < queryList.size(); i++) {
                buffer.append(i == 0 ? "?" : "&");

                NameValuePair nvp = queryList.get(i);

                buffer.append(URLEncoder.encode(nvp.getName(), encoding))
                        .append("=");
                if (nvp.getValue() != null) {
                    buffer.append(URLEncoder.encode(nvp.getValue(), encoding));
                }
            }

            return buffer.toString();
        } catch (URISyntaxException e) {
            throw e;
        } catch (UnsupportedEncodingException ex) {
            throw ex;
        }
    }


    private static Charset GetContentType(HttpEntity entity, String htmlEncoding) {
        String charsetStr = null;
        Charset charset = null;
        try {
            if (entity.getContentType().getValue() != null) {
                String contentType = entity.getContentType().getValue()
                        .toLowerCase();
                int m = contentType.indexOf("charset");
                if (m >= 0) {
                    int begin = contentType.indexOf("=", m);
                    if (begin > 0) {
                        begin++;
                        m = contentType.indexOf(" ", begin);
                        if (m < 0) {
                            m = contentType.indexOf(";", begin);
                        }
                        if (m > begin) {
                            charsetStr = contentType.substring(begin, m).trim();
                        } else {
                            charsetStr = contentType.substring(begin).trim();
                        }
                        charset = Charset.forName(charsetStr);
                    }
                }
            }
        } catch (Exception e) {
            charset = null;
        }
        if (charset == null) {
            try {
                charset = Charset.forName(htmlEncoding);
            } catch (Exception e) {
                charset = Charset.defaultCharset();
            }
        }
        return charset;
    }
    private byte[] GetContentBytes(HttpEntity entity) throws Exception {
        String encoding = "";
        if (entity.getContentEncoding() != null) {
            encoding = entity.getContentEncoding().getValue();
        }
        if ((encoding.trim().equalsIgnoreCase("gzip")) || encodingGizp()) {
            GzipDecompressingEntity gzipEntity = new GzipDecompressingEntity(
                    entity);
            return HttpUnzipUtil.UnzipContent(gzipEntity.getContent());
        }
        if ((encoding.trim().equalsIgnoreCase("deflate")) || encodingDeflate()) {
            DeflateDecompressingEntity deflateEntity = new DeflateDecompressingEntity(
                    entity);
            return HttpUnzipUtil.UnzipContent(deflateEntity.getContent());
        }
        return EntityUtils.toByteArray(entity);
    }


    public boolean encodingGizp() {
        return false;
        // (httpParam != null) && (((Boolean) httpParam
        // .getParameter("customhttpclient.acceptencoding.gzip"))
        // .booleanValue()))) {

    }

    public boolean encodingDeflate() {
        return false;
        // (httpParam != null) && (((Boolean) httpParam
        // .getParameter("customhttpclient.acceptencoding.deflate"))
        // .booleanValue()))) {

    }


}
